#ifndef _STL_UTIL_APPLY_H_
#define _STL_UTIL_APPLY_H_

#include "./stl_util_define.h"

namespace Holders {

	/*!
		function for applying changes to each item in a container.
		\param i the initial iterator of the interval
		\param e the ending iterator of the interval
		\param func the function desired to use in each object
		\sa Set& apply( Set &list, Func func );
	*/
	template <class Iter, class Func>
		void apply( Iter i, Iter end, const Func &func ) {
			for(; i != end ; ++i) {
				(*i) = func( *i );
			}
		};

	/*!
		function for applying changes to each item in a container.
		\param list the desired container to be modified
		\param func the function desired to use in each object
		\return a reference to the modified container
		\sa Set check( const Set &list, const Func &func );
		\code
		deque< double > list;
		list, 1.2, 2.8, 3.5;
				
		cout << list << endl;						// prints [ 1.2 2.8 3.5 ]
		cout << apply( asdf, Round ) << endl;	// prints [ 1 3 4 ]
		cout << list << endl;						// prints [ 1 3 4 ]
		\endcode
		\code
		// if using Lambda functions
		deque< double > list;
		list, 1.0, 2.0, 3.0;
				
		cout << list << endl;							// prints [ 1.0 2.0 3.0 ]
		Lambda< Var > x = Var();
		cout << apply( asdf, x + x ) << endl;		// prints [ 2.0 4.0 6.0 ]
		cout << list << endl;							// prints [ 2.0 4.0 6.0 ]
		\endcode
	*/
	template <class Set, class Func>
		Set& apply( Set &list, const Func &func ) {
			apply(list.begin(), list.end(), func);
			return list;
		};

	//! holder class for apply.
	/*!
		class for calling apply with operator().
	*/
	template <class Set, class Func>
		class ApplyHolder{
		protected:
			/*! 1st parameter for apply() */
			Set &list;
			/*! 2nd parameter for apply() */
			Func func;
		public:
			/*!
				constructor
				\param list 1st parameter for apply()
				\param func 2nd parameter for apply()
				\sa Set& apply( Set &list, const Func &func );
			*/
			ApplyHolder( Set &list, const Func &func ): list(list), func(func) {};
			/*!
				copy constructor
				\param org the original object
				\sa ApplyHolder( Set &list, const Func &func );
			*/
			ApplyHolder( const ApplyHolder &org ): list(org.list), func(org.func) {};
					
			/*!
				operator for using the apply with the parameters defined
				by its attributes.
				\return the same return as apply().
				\sa Set& apply( Set &list, const Func &func );
			*/
			inline Set& operator()() {
				return apply( list, func );
			};
		};
			
	/*!
		Function for creating a SelectHolder without telling
		the template parameters.
		\param list 1st parameter for apply()
		\param func 2nd parameter for apply()
		\sa Set& apply( Set &list, const Func &func );
		\return a reference to the created object.
	*/
	template <class Set, class Func>
		inline ApplyHolder<Set,Func>& Applyer( Set &list, const Func &func ){
			return * ( new ApplyHolder<Set,Func>( list, func ) );
		};

};

#endif // _STL_UTIL_APPLY_H_
